/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 *
 */
/** @author Ahmed
 */
/**
 * @purpose make an iso server using the JPOS library
 */
package blackbirdisoserver;

import java.io.*;

import org.jpos.iso.*;
import org.jpos.q2.QBeanSupport;
import org.jpos.util.*;
import org.jpos.iso.channel.*;
import org.jpos.iso.packager.*;

import java.sql.*;
import java.util.*;
import org.jpos.core.CardHolder;
import blackbirdisoserver.ConnectionManager;

/**
 * @author Ahmed
 * @version 1.0.1
 */

public class Main implements ISORequestListener
{
	/**
	 * the JJ KICKS hehe
	 */
	public static long maxx = 0;
	static String str = "Convenient lock string";
	ConnectionManager conn = new ConnectionManager();

	public Main()
	{
		super();
	}

	public boolean process(ISOSource source, ISOMsg m)
	{
		System.out.println("Attempting to process request from Source with Message");

		ArrayList<TransactionData> Info = new ArrayList<TransactionData>();
		ArrayList<TransactionData> AuthunInfo = new ArrayList<TransactionData>();
		TransactionData TrData = new TransactionData();
		String terminalID = new String();
		String transactionNum = new String();
		String amount = new String();

		ISOChannel cccc = (ISOChannel) source;

		try
		{
			CardHolder caHolder;

			ISOServer srv = (ISOServer) NameRegistrar.get("serverchannel");

			ISOMUX mux = (ISOMUX) NameRegistrar.get("BlackBirdMUX");
			// rock'n roll
			boolean isEnd = true;
			boolean isFirst500 = true;
			System.out.println("MTI: " + m.getMTI());
			while (true)
			{
				if ("0320".equals(m.getMTI()))
				{
					System.out.println("MTI is 0320");
					for (int i = 0; i < 63; i++)
					{
						if (m.hasField(i))
						{
							// make strings to insert into database table
							if (i == 41)
							{
								terminalID = m.getString(i);
							} else if (i == 11)
							{
								transactionNum = m.getString(i);
							} else if (i == 4)
							{
								amount = m.getString(i);
							}
						}
					}
					caHolder = new CardHolder(m);
					Info.add(new TransactionData(terminalID, transactionNum,
							amount, caHolder.getPAN()));
				}

				print_msg(m);
//				printConnectionInfo(m);
				if ("0500".equals(m.getMTI()) && "920000".equals(m.getString(3)))
				{
					System.out.println("MTI is 0500 and string 3 920000");
//					printConnectionInfo(m);
					m.setResponseMTI();
					m.set(39, "95");
					m.unset(63);
					m.unset(42);
					m.unset(60);
					cccc.send(m);
				} else if ("0500".equals(m.getMTI()) && "960000".equals(m.getString(3)))
				{
					System.out.println("MTI is 0500 and string 3 is 960000");
					m.setResponseMTI();
					m.set(39, "00");
					m.unset(63);
					m.unset(42);
					m.unset(60);

					boolean ttr = insertIntoDatabase(Info);
					if (ttr)
					{
						cccc.send(m);
						return true;
					} else
					{
						m.set(39, "95");
						cccc.send(m);
						return false;
					}
				} else if ("0320".equals(m.getMTI()))
				{
					System.out.println("MTI is 0320 tany marra");
					caHolder = new CardHolder(m);
					m.setResponseMTI();
					m.set(39, "00");
					m.unset(63);
					m.unset(42);
					m.unset(60);
					cccc.send(m);
				} else
				{
					System.out.println("else ay 7aga tanya");
					caHolder = new CardHolder(m);
//					printConnectionInfo(m);
					for (int i = 0; i < 63; i++)
					{
						if (m.hasField(i))
						{
							// make strings to insert into database table
							if (i == 41)
							{
								terminalID = m.getString(i);
							} else if (i == 11)
							{
								transactionNum = m.getString(i);
							} else if (i == 4)
							{
								amount = m.getString(i);
							}
						}
					}
					System.out.println("Will insert stuff inside the database NOW");
					AuthunInfo.add(new TransactionData(terminalID, transactionNum, amount, caHolder.getPAN()));
					Boolean ttr = insertIntoAuthDatabase(AuthunInfo);
					System.out.println("Transaction inserted into database: " + ttr.toString());
					// If trx didnt make it into database, send failure
					if (!ttr)
					{
						m.set(39, "95");
					}
					m.setResponseMTI();
					m.set(39, "00");
					m.unset(63);
					m.unset(42);
					m.unset(60);
					source.send(m);
					return true;
				}

				m = cccc.receive();

			}
		} catch (Exception ex)
		{
			ex.printStackTrace();
		}
		return true;


//		try
//		{
//			m.setResponseMTI();
//			m.set(3, "12");
//			m.set(39, "00");
//			source.send(m);
//		}
//		catch (ISOException e)
//		{
//			e.printStackTrace();
//		}
//		catch (IOException e)
//		{
//			e.printStackTrace();
//		}
//		return true;
	}

	public static void main(String[] args) throws Exception
	{

		Logger logger = new Logger();
		logger.addListener(new SimpleLogListener(System.out));

		byte[] TPDU = new byte[5];
		TPDU[0] = 60;
		TPDU[1] = 0;
		TPDU[2] = 1;
		TPDU[3] = 0;
		TPDU[4] = 0;
//		ServerChannel channel = new NACChannel(new ISO87BPackager(), TPDU);
		ServerChannel channel = new XMLChannel(new XMLPackager());
//		ServerChannel channel = new NACChannel
		((LogSource)channel).setLogger(logger, "channel");
		// register this channel to get it in the process method
		channel.setName("blackbird");

		ISOMUX mux = new ISOMUX(channel);
		NameRegistrar.register("BlackBirdMUX", mux);

		//Not needed, null by default creates a new ThreadPool(1, 100)
//		ThreadPool thPool = new ThreadPool(10, 20);
		ISOServer server = new ISOServer(8484, channel, null);
		server.setLogger(logger, "server");
		server.addISORequestListener(new Main());

		NameRegistrar.register("serverchannel", server);


		new Thread(server).start();
	}

	synchronized public boolean insertIntoDatabase(ArrayList<TransactionData> Info)
	{
		System.out.println("Attempting to insert data into Database");
		String insertStrQuery = new String();
		Integer listSize = Info.size();
		TransactionData TrData = new TransactionData();
		try
		{
			conn.createConnection();

			String[] arrTerminalID = new String[listSize];
			String[] arrTransactionNum = new String[listSize];
			String[] arrAmount = new String[listSize];
			String[] arrCardNo = new String[listSize];
			for (int i = 0; i < listSize; i++)
			{
				TrData = Info.get(i);
				arrTerminalID[i] = TrData.terminalID;
				arrTransactionNum[i] = TrData.transactionNum;
				arrAmount[i] = TrData.amount;
				arrCardNo[i] = TrData.cardNumber;

				insertStrQuery = "INSERT INTO pos_settlement ( TerminalID, Stan, CardNo, Amount) values (\""
						+ arrTerminalID[i]
						+ "\",\""
						+ arrTransactionNum[i]
						+ "\",\""
						+ arrCardNo[i]
						+ "\",\""
						+ arrAmount[i]
						+ "\")";
				conn.executeNonQuery(insertStrQuery);
			}
			conn.commit();
			conn.close();
		} catch (Exception e)
		{
			try
			{
				conn.close();
				return false;
			} catch (Exception x)
			{
				x.printStackTrace();
			}
			e.printStackTrace();
			return false;
		}
		return true;
	}

	synchronized public boolean insertIntoAuthDatabase(ArrayList<TransactionData> Info)
	{
		System.out.println("Attempting to insert data into Auth Database");
		conn.createConnection();

		String insertStrQuery = new String();
		Integer listSize = Info.size();
		TransactionData TrData = new TransactionData();
		try
		{
			String[] arrTerminalID = new String[listSize];
			String[] arrTransactionNum = new String[listSize];
			String[] arrAmount = new String[listSize];
			String[] arrCardNo = new String[listSize];

			for (int i = 0; i < listSize; i++)
			{
				TrData = Info.get(i);
				arrTerminalID[i] = TrData.terminalID;
				arrTransactionNum[i] = TrData.transactionNum;
				arrAmount[i] = TrData.amount;
				arrCardNo[i] = TrData.cardNumber;

				insertStrQuery = "INSERT INTO pos_auth ( TerminalID, Stan, CardNo, Amount) values (\""
						+ arrTerminalID[i]
						+ "\",\""
						+ arrTransactionNum[i]
						+ "\",\""
						+ arrCardNo[i]
						+ "\",\""
						+ arrAmount[i]
						+ "\")";
				conn.executeNonQuery(insertStrQuery);
			}
			conn.commit();
			conn.close();

		} catch (Exception e)
		{
			try
			{
				conn.close();
				return false;
			} catch (Exception x)
			{
				x.printStackTrace();
			}
			e.printStackTrace();
			return false;
		}
		return true;
	}

	private synchronized static void print_msg(ISOMsg rec) throws Exception
	{
//		byte[] foo = rec.pack();
		System.out.println("Attempting to print message");
		ISOPackager AhPackager = new ISO87BPackager();
		rec.setPackager(AhPackager);
		ISOBasePackager gg = (ISOBasePackager) AhPackager;
		System.out
				.println("|++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++|");
		for (int i = 0; i < 65; i++)
		{
			if (rec.hasField(i))
			{
				String str = rec.getString(i);
				ISOFieldPackager GG = gg.getFieldPackager(i);
				String Desc = GG.getDescription();
				int len = Desc.length() + str.length();
				if (len < 70)
				{
					for (int c = len; c < 70; c++)
					{
						Desc += " ";
					}
				}
				Desc += str;
				System.out.printf("[%02d]  %s\n", i, Desc);
			}
		}
	}

	private synchronized static void printConnectionInfo(ISOMsg rec)
	{
		System.out.println("Attempting to print Connection Info");
		System.out.println("Starting Session with Terminal ID: " + rec.getString(41));
		String trxType = new String();
		try
		{
			if ("0200".equals(rec.getMTI()))
			{
				trxType = "Sale/Debit";
			} else if ("0100".equals(rec.getMTI()))
			{
				trxType = "Balance Inquirey";
			} else if ("0220".equals(rec.getMTI()))
			{
				trxType = "Offline (Sale/Refund)";
			} else if ("0500".equals(rec.getMTI()))
			{
				trxType = "Settlement";
			}

		} catch (Exception ex)
		{

		}
		System.out.println("Transaction type: " + trxType + "\n");
	}
}
